﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Net.Sockets;
using System.Windows.Forms;
using System.Collections;

namespace wssServer
{
    public partial class wssServer : ServiceBase
    {
        private SocketServer Socket;
        private List<Computador> hostClients;
        private int hostPos;
        private int lastPasswdInserted;

        public wssServer()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            this.TimerWork.Interval = Convert.ToInt32(Functions.lerRegKey("timer")) * 60000;
            Functions.gravarErro("Processo iniciará em " + this.TimerWork.Interval / 60000 + " minuto(s).");
        }

        protected override void OnStop()
        {
            this.TimerWork.Stop();
        }

        public void OnTimeWork(object sender, EventArgs e)
        {
            Functions.gravarErro("Processo de alteração iniciado.");
            this.hostPos = 0;
            this.hostClients = this.RecuperarComputadores();
            this.ConectToNextHost();
        }

        private void OnTimeOut(object sender, EventArgs e)
        {
            this.EndTimeWork();
        }

        private void ConectToNextHost()
        {
            if (hostClients.Count > this.hostPos)
            {
                try
                {
                    Computador host = hostClients[this.hostPos];
                    this.hostPos++;

                    this.Socket = new SocketServer(host.nomeCompleto, 2252);
                    if (this.Socket.Connect())
                    {
                        this.Socket.OnRead += new SocketServer.ConnectionDelegate(this.OnReceiverReply);
                        this.SendMessage("RAS");
                    }
                }
                catch (Exception ex)
                {
                    Functions.gravarErro(ex.Message);
                }
            }
        }

        private void OnReceiverReply(Socket soc)
        {
            string[] Message = Functions.splitMessage(this.Socket.ReceivedText);

            switch (Message[0])
            {
                //Realizar validação dos dados
                case "RVD":
                    string licenca = Message[1];
                    string senha = Message[2];

                    if (this.ValidarLicenca(licenca))
                    {
                        if (this.ValidarSenha(senha))
                        {
                            if (this.GravarSenha(senha))
                            {
                                this.SendMessage(String.Format("CAS||{0}", senha));
                            }
                        }
                        else
                        {
                            this.SendMessage("ESI");
                        }
                    }
                    else
                    {
                        this.SendMessage("ELI");
                    }

                    break;
                //Sucesso na alteração de Senha
                case "SAS":
                    this.AlterarStatusSenha();
                    this.EndTimeWork();

                    break;
                //Erro ao Alterar Senha
                case "EAS":
                default:
                    this.EndTimeWork();
                    break;
            }
        }

        private void EndTimeWork(){
            this.TimerOut.Stop();
            this.Socket.Disconnect();
            this.ConectToNextHost();
        }

        private void SendMessage(string Message)
        {
            Functions.gravarErro("O servidor envio ao cliente " + this.Socket.RemoteHost + " a seguinte mensagem: " + Message);
            this.Socket.SendText(Message);
            this.TimerOut.Start();
        }

        protected List<Computador> RecuperarComputadores()
        {
            ArrayList arrComputadores = MySqlConnector.Listar("computadores", "`ativo` = 'A'");
            List<Computador> ComputadoresList = new List<Computador>();
            
            foreach(string[] dr in arrComputadores)
            {
                Computador ComputadorItem = new Computador();

                ComputadorItem.coComputor   = Convert.ToInt32(dr[0]);
                ComputadorItem.coLicenca    = Convert.ToInt32(dr[2]);
                ComputadorItem.nomeCompleto = Convert.ToString(dr[3]);
                ComputadorItem.enderecoMac  = Convert.ToString(dr[4]);
                ComputadorItem.nuIP         = Convert.ToString(dr[7]);
                ComputadorItem.ativo        = Convert.ToChar(dr[8]);

                ComputadoresList.Add(ComputadorItem);
            }

            return ComputadoresList;
        }

        protected bool ValidarLicenca(string Licenca)
        {
            if (Functions.ValidarLicenca(Licenca))
            {

                string Host = this.Socket.RemoteHost;

                string sql = string.Format("SELECT `registro_chave` FROM `licencas` AS l INNER JOIN `computadores` AS c ON (l.co_licenca = c.co_licenca) WHERE c.nome_computador = '{0}' AND l.registro_chave = '{1}'", Host, Licenca);

                ArrayList arrLicencas = MySqlConnector.Pesquisar(sql);

                return (arrLicencas.Count == 0);
            }
            else
            {
                return false;
            }
        }

        protected bool ValidarSenha(string Senha)
        {
            string Host = this.Socket.RemoteHost;

            string sql = string.Format( "SELECT * FROM `senhas` WHERE `senha_atual` = '{0}' AND `co_computador` = (SELECT `co_computador` FROM `computadores` WHERE `nome_computador` = '{1}') AND `ativa` = 'A'", Senha, Host);

            ArrayList arrSenhas = MySqlConnector.Pesquisar(sql);

            return (arrSenhas.Count == 0);
        }

        protected bool GravarSenha(string Senha)
        {
            string Host = this.Socket.RemoteHost;

            string sql = string.Format("INSERT INTO `senhas` ( `co_computador` , `senha_atual` , `dt_alteracao` , `ativa` ) VALUES ( (SELECT `co_computador` FROM `computadores` WHERE `nome_computador` = '{0}'), '{1}', CURRENT_TIMESTAMP , 'I' )", Host, Senha );

            this.lastPasswdInserted = MySqlConnector.Inserir(sql);
            
            return this.lastPasswdInserted > 0;
        }

        protected bool AlterarStatusSenha()
        {
            string sql = string.Format("UPDATE `senhas` SET `ativa` = 'A' WHERE `co_senha` = {0}", this.lastPasswdInserted);

            return MySqlConnector.Query(sql);
        }

    }
}